import os
import threading
import tkinter as tk
from tkinter import messagebox, ttk, Scrollbar
from datetime import datetime
from config import CURRENT_WX_NAME, PROMPT_FILE
import json

from database import DatabaseManager

# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 拼接配置文件的路径
config_file_path = os.path.join(script_dir, 'config.json')

# 读取 config.json 文件
try:
    with open(config_file_path, 'r', encoding='utf-8') as f:
        config = json.load(f)
except FileNotFoundError:
    print(f"配置文件 {config_file_path} 未找到")
    config = {}

# 获取配置信息
CURRENT_WX_NAME = config['CURRENT_WX_NAME']
PROMPT_FILE = config['PROMPT_FILE']




class ColumnResizer:
    def __init__(self, container, canvas, cols, config_path):
        self.container = container
        self.canvas = canvas
        self.cols = cols
        self.config_path = config_path
        self.drag_data = {"x": 0, "col": None}
        self.separators = []

        # 初始化列宽配置
        self._load_column_widths()  # 修改为私有方法

        # 创建可拖拽的分隔线
        for col in range(1, len(cols)):
            sep = ttk.Separator(self.container, orient=tk.VERTICAL)
            sep.place(
                in_=self.container,
                x=self._get_column_right_edge(col - 1),  # 使用辅助方法
                rely=0,
                relheight=1,
                bordermode="outside"
            )
            sep.bind("<ButtonPress-1>", lambda e, c=col - 1: self.drag_start(e, c))
            sep.bind("<B1-Motion>", self.drag_motion)
            sep.bind("<ButtonRelease-1>", self.drag_stop)
            sep.config(cursor="sb_h_double_arrow")
            self.separators.append(sep)

        # 配置分隔线样式
        style = ttk.Style()
        style.configure("TSeparator", background="#666666", width=2)


    def _load_column_widths(self):
        # 原代码缺少宽度校验（添加范围限制）
        MIN_WIDTH = 50
        MAX_WIDTH = 1000
        try:
            if os.path.exists(self.config_path):
                with open(self.config_path, 'r') as f:
                    widths = json.load(f)
                    for col, width in widths.items():
                        col_index = int(col)
                        if col_index < len(self.cols):
                            # 添加范围限制
                            valid_width = max(MIN_WIDTH, min(int(width), MAX_WIDTH))
                            self.container.grid_columnconfigure(
                                col_index,
                                minsize=valid_width  # 使用修正后的值
                            )
        except Exception as e:
            print(f"加载列宽配置失败: {str(e)}")

    def _save_column_widths(self):
        """保存当前列宽设置到文件"""
        try:
            widths = {}
            for col in self.cols:
                col_info = self.container.grid_bbox(0, col)
                if col_info:
                    widths[str(col)] = col_info[2]  # 获取实际列宽
            with open(self.config_path, 'w') as f:
                json.dump(widths, f, indent=2)
        except Exception as e:
            print(f"保存列宽配置失败: {str(e)}")

    def _get_column_right_edge(self, col):
        """获取指定列的右边界坐标"""
        x, _, width, _ = self.container.grid_bbox(0, col)
        return x + width

    def drag_start(self, event, col):
        """开始拖拽"""
        self.drag_data["col"] = col
        self.drag_data["x"] = event.x
        self.original_width = self.container.grid_bbox(0, col)[2]

    def drag_motion(self, event):
        """拖拽过程中"""
        if self.drag_data["col"] is None:
            return

        col = self.drag_data["col"]
        delta = event.x - self.drag_data["x"]
        new_width = max(self.original_width + delta, 50)  # 最小宽度50px

        # 更新列配置
        self.container.grid_columnconfigure(col, minsize=new_width)

        # 更新消息内容列的控件宽度
        for child in self.container.winfo_children():
            info = child.grid_info()
            if info["column"] == col and isinstance(child, tk.Message):
                child.config(width=new_width)

        # 更新分隔线位置
        for sep in self.separators:
            sep_col = int(sep.place_info()["x"]) // self.container.grid_bbox(0, 0)[2]
            if sep_col == col:
                sep.place_configure(x=self._get_column_right_edge(col))

        self.container.update_idletasks()
        self.canvas.config(scrollregion=self.canvas.bbox("all"))

    def drag_stop(self, event):
        """结束拖拽"""
        self._save_column_widths()
        self.drag_data["col"] = None
        self.drag_data["x"] = 0

class BotUI:
    def __init__(self, root, bot):
        self.root = root
        self.root.title("微信机器人管理界面")
        self.bot = bot
        self.friends_cache = None
        self.current_displayed_friends = None
        self.friends_lock = threading.Lock()  # 移到 __init__ 方法中

        # 添加配置路径
        self.config_path = os.path.join(script_dir, 'config.json')  # 新增
        self.config_dir = os.path.join(script_dir, 'chat_config')
        os.makedirs(self.config_dir, exist_ok=True)
        # 确保配置文件路径正确
        self.column_config_path = os.path.join(self.config_dir, "column_widths.json")

        # 新增检查确保路径是文件
        if os.path.isdir(self.column_config_path):
            os.rmdir(self.column_config_path)  # 删除错误创建的目录


        # 顶部日期时间和昵称显示
        top_frame = tk.Frame(root)
        top_frame.pack(fill=tk.X)

        self.date_time_label = tk.Label(top_frame)
        self.date_time_label.pack(side=tk.LEFT, padx=10, pady=5)

        self.nickname_label = tk.Label(top_frame, text=f"已登录昵称: {CURRENT_WX_NAME}")
        self.nickname_label.pack(side=tk.RIGHT, padx=10, pady=5)

        self.update_date_time()

        # 左侧功能侧栏
        self.sidebar = tk.Frame(root, width=200)
        self.sidebar.pack(side=tk.LEFT, fill=tk.Y)

        button_width = 15
        self.friends_button = tk.Button(self.sidebar, text="好友列表", command=self.show_friends, width=button_width)
        self.friends_button.pack(pady=10, padx=10, anchor=tk.CENTER)

        self.listen_list_button = tk.Button(self.sidebar, text="监听列表", command=self.show_listen_list, width=button_width)
        self.listen_list_button.pack(pady=10, padx=10, anchor=tk.CENTER)

        self.message_view_button = tk.Button(self.sidebar, text="消息查看", command=self.show_message_view, width=button_width)
        self.message_view_button.pack(pady=10, padx=10, anchor=tk.CENTER)

        self.prompt_edit_button = tk.Button(self.sidebar, text="提示词编辑", command=self.show_prompt_edit, width=button_width)
        self.prompt_edit_button.pack(pady=10, padx=10, anchor=tk.CENTER)

        # 添加配置管理按钮
        self.config_edit_button = tk.Button(self.sidebar, text="配置管理", command=self.show_config_edit, width=button_width)
        self.config_edit_button.pack(pady=10, padx=10, anchor=tk.CENTER)

        # 显示区域
        self.display_frame = tk.Frame(root)
        self.display_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        # 分隔线
        separator = ttk.Separator(root, orient=tk.VERTICAL)
        separator.pack(side=tk.LEFT, fill=tk.Y, padx=5)

        self.root.bind("<Configure>", self.on_window_resize)


    def update_date_time(self):
        current_date_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.date_time_label.config(text=current_date_time)
        self.root.after(1000, self.update_date_time)

    def on_window_resize(self, event):
        max_button_width = 20
        for widget in self.sidebar.winfo_children():
            if isinstance(widget, tk.Button):
                widget.config(width=min(max_button_width, widget.winfo_width() // 10))



    def show_friends(self):
        self.friends_lock = threading.Lock()
        if self.friends_cache is None:
            def get_friends_async():
                friends = self.bot.wx.GetAllFriends()
                with self.friends_lock:
                    self.friends_cache = friends
                self.display_friends(friends)

            threading.Thread(target=get_friends_async).start()
        else:
            with self.friends_lock:
                self.display_friends(self.friends_cache)

    def display_friends(self, friends):
        for widget in self.display_frame.winfo_children():
            widget.destroy()

        # 搜索和筛选区域
        search_frame = tk.Frame(self.display_frame)
        search_frame.pack(fill=tk.X, padx=10, pady=5)

        search_label = tk.Label(search_frame, text="搜索:")
        search_label.pack(side=tk.LEFT, padx=5)
        search_entry = tk.Entry(search_frame)
        search_entry.pack(side=tk.LEFT, padx=5)

        tag_label = tk.Label(search_frame, text="标签筛选:")
        tag_label.pack(side=tk.LEFT, padx=5)
        tag_entry = tk.Entry(search_frame)
        tag_entry.pack(side=tk.LEFT, padx=5)

        search_button = tk.Button(search_frame, text="搜索",
                                  command=lambda: self.filter_friends(search_entry.get(), tag_entry.get()))
        search_button.pack(side=tk.LEFT, padx=5)

        show_all_button = tk.Button(search_frame, text="显示全部", command=lambda: self.display_friends(self.friends_cache))
        show_all_button.pack(side=tk.LEFT, padx=5)

        # 列头
        column_frame = tk.Frame(self.display_frame, bd=1, relief=tk.SOLID)
        column_frame.pack(fill=tk.X, padx=10, pady=5)

        remark_header = tk.Label(column_frame, text="备注", width=20, anchor=tk.W)
        remark_header.pack(side=tk.LEFT, padx=5, pady=5)

        nickname_header = tk.Label(column_frame, text="昵称", width=20, anchor=tk.W)
        nickname_header.pack(side=tk.LEFT, padx=5, pady=5)

        tags_header = tk.Label(column_frame, text="标签", width=20, anchor=tk.W)
        tags_header.pack(side=tk.LEFT, padx=5, pady=5)

        button_header = tk.Label(column_frame, text="操作", width=30, anchor=tk.W)
        button_header.pack(side=tk.LEFT, padx=5, pady=5)

        # 创建一个带有滚动条的画布
        canvas = tk.Canvas(self.display_frame)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 创建垂直滚动条并关联到canvas
        v_scroll = tk.Scrollbar(self.display_frame, orient=tk.VERTICAL, command=canvas.yview)
        v_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.configure(yscrollcommand=v_scroll.set)

        def _on_mousewheel(event):
            canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

        canvas.bind_all("<MouseWheel>", _on_mousewheel)

        scrollbar = Scrollbar(self.display_frame, command=canvas.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.configure(yscrollcommand=scrollbar.set)

        frame = tk.Frame(canvas)
        canvas.create_window((0, 0), window=frame, anchor=tk.NW)

        for i, friend in enumerate(friends):
            remark = friend.get('remark')
            nickname = friend.get('nickname', '')
            if remark is None:
                remark = nickname
            tags = friend.get('tags', [])
            if tags is None:
                tags = []

            tag_str = ', '.join(tags)

            info_frame = tk.Frame(frame, bd=1, relief=tk.SOLID)
            info_frame.pack(fill=tk.X, padx=10, pady=5)

            remark_label = tk.Label(info_frame, text=remark, width=20, anchor=tk.W)
            remark_label.pack(side=tk.LEFT, padx=5, pady=5)

            nickname_label = tk.Label(info_frame, text=nickname, width=20, anchor=tk.W)
            nickname_label.pack(side=tk.LEFT, padx=5, pady=5)

            tags_label = tk.Label(info_frame, text=tag_str, width=20, anchor=tk.W)
            tags_label.pack(side=tk.LEFT, padx=5, pady=5)

            button_frame = tk.Frame(info_frame)
            button_frame.pack(side=tk.RIGHT)

            add_button = tk.Button(button_frame, text="添加",
                                   command=lambda f=friend: self.add_to_listen_list(f))
            add_button.pack(side=tk.LEFT, padx=5)

            remove_button = tk.Button(button_frame, text="移除",
                                      command=lambda f=friend: self.remove_from_listen_list(f))
            remove_button.pack(side=tk.LEFT, padx=5)

        frame.update_idletasks()
        canvas.config(scrollregion=canvas.bbox("all"))
        self.current_displayed_friends = friends

    def filter_friends(self, search_text, tag_text):
        filtered_friends = []
        for friend in self.friends_cache:
            remark = friend.get('remark')
            nickname = friend.get('nickname', '')
            if remark is None:
                remark = nickname
            tags = friend.get('tags', [])
            if tags is None:
                tags = []
            tag_str = ', '.join(tags)

            if (search_text.lower() in remark.lower() or search_text.lower() in nickname.lower()) and (
                    not tag_text or tag_text in tag_str):
                filtered_friends.append(friend)

        self.display_friends(filtered_friends)

    def add_to_listen_list(self, friend):
        nickname = friend.get('nickname')
        if nickname:
            try:
                self.bot.add_to_listen_list(nickname)
                messagebox.showinfo("提示", f"已添加 {nickname} 到监听列表")
                # 实时更新监听列表显示
                self.show_listen_list()
            except Exception as e:
                messagebox.showerror("错误", f"添加失败: {str(e)}")

    def remove_from_listen_list(self, friend):
        nickname = friend.get('nickname')
        if nickname:
            try:
                self.bot.remove_from_listen_list(nickname)
                messagebox.showinfo("提示", f"已从监听列表移除 {nickname}")
                # 实时更新监听列表显示
                self.show_listen_list()
            except Exception as e:
                messagebox.showerror("错误", f"移除失败: {str(e)}")

    def show_listen_list(self):
        # 清空显示框架中的所有部件
        for widget in self.display_frame.winfo_children():
            widget.destroy()

        listen_list = self.bot.get_listen_list()

        canvas = tk.Canvas(self.display_frame)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = Scrollbar(self.display_frame, command=canvas.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        canvas.configure(yscrollcommand=scrollbar.set)

        frame = tk.Frame(canvas)
        canvas.create_window((0, 0), window=frame, anchor=tk.NW)

        for listener in listen_list:
            listener_frame = tk.Frame(frame, bd=1, relief=tk.SOLID)
            listener_frame.pack(fill=tk.X, padx=10, pady=5)
            listener_label = tk.Label(listener_frame, text=listener, anchor=tk.W)
            listener_label.pack(pady=5, padx=10, fill=tk.X)

        frame.update_idletasks()
        canvas.config(scrollregion=canvas.bbox("all"))

    def show_message_view(self):
        selection_window = tk.Toplevel(self.root)
        selection_window.title("选择好友查看消息")

        listen_list = self.bot.get_listen_list()

        def select_friend():
            selected_friend = friend_var.get()
            if selected_friend:
                selection_window.destroy()
                self.show_chat_history(selected_friend)

        friend_var = tk.StringVar(selection_window)
        friend_var.set(listen_list[0] if listen_list else "")

        option_menu = tk.OptionMenu(selection_window, friend_var, *listen_list)
        option_menu.pack(pady=10)

        select_button = tk.Button(selection_window, text="选择", command=select_friend)
        select_button.pack(pady=10)

    def show_chat_history(self, selected_friend):
        # 清空当前显示内容
        for widget in self.display_frame.winfo_children():
            widget.destroy()
        # 创建固定按钮容器（位于 display_frame 底部）
        button_frame = tk.Frame(self.display_frame)
        button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=5)

        # 创建滚动区域容器
        canvas_frame = tk.Frame(self.display_frame)
        canvas_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        # 创建主画布和滚动条
        canvas = tk.Canvas(canvas_frame)
        h_scrollbar = tk.Scrollbar(self.display_frame, orient=tk.HORIZONTAL, command=canvas.xview)
        v_scrollbar = tk.Scrollbar(self.display_frame, command=canvas.yview)

        canvas.configure(
            xscrollcommand=h_scrollbar.set,
            yscrollcommand=v_scrollbar.set,
            highlightthickness=0
        )

        h_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
        v_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        container = tk.Frame(canvas)
        canvas.create_window((0, 0), window=container, anchor=tk.NW)

        # 列配置
        container.grid_columnconfigure(0, minsize=100, weight=0)
        container.grid_columnconfigure(1, minsize=200, weight=1)
        container.grid_columnconfigure(2, minsize=150, weight=0)

        # 移动刷新按钮到固定容器
        refresh_button = tk.Button(button_frame,
                                   text="刷新",
                                   command=lambda: [
                                       DatabaseManager.manual_flush(),  # 添加手动刷新
                                       self.show_chat_history(selected_friend)
                                   ])
        refresh_button.pack(side=tk.RIGHT, padx=10)
        # 创建标题行（添加列边框）
        headers = ["昵称", "消息内容", "发送时间"]
        for col, text in enumerate(headers):
            header = tk.Label(container,
                              text=text,
                              relief="solid",
                              bd=1,
                              bg="#f0f0f0",
                              padx=5,
                              pady=3)
            header.grid(row=0, column=col, sticky="nsew")

        # 获取聊天记录
        messages = self.bot.get_chat_history(selected_friend)  # 假设有此方法

        # 添加聊天记录（精确列对齐）
        for row, msg in enumerate(messages, start=1):
            # 消息行（使用单独列布局）
            msg_row = row * 2 - 1
            nickname_label = tk.Label(container,
                                      text=selected_friend,
                                      anchor=tk.W,
                                      bd=1,
                                      relief="solid",
                                      padx=5)
            message_label = tk.Label(container,
                                     text=msg["message"],
                                     wraplength=2000,
                                     anchor=tk.W,
                                     bd=1,
                                     relief="solid",
                                     padx=5)
            timestamp = msg["message"].split("]")[0].strip("[]")
            time_label = tk.Label(container,
                                  text=timestamp,
                                  anchor=tk.W,
                                  bd=1,
                                  relief="solid",
                                  padx=5)

            # 使用grid布局精确对齐
            nickname_label.grid(row=msg_row, column=0, sticky="nsew")
            message_label.grid(row=msg_row, column=1, sticky="nsew")
            time_label.grid(row=msg_row, column=2, sticky="nsew")

            # 回复行
            reply_row = row * 2
            reply_nickname = tk.Label(container,
                                      text=CURRENT_WX_NAME,
                                      anchor=tk.W,
                                      bg="#e0ffe0",
                                      bd=1,
                                      relief="solid",
                                      padx=5)
            reply_content = tk.Label(container,
                                     text=msg.get("reply", ""),
                                     wraplength=2000,
                                     bg="#e0ffe0",
                                     anchor=tk.W,
                                     bd=1,
                                     relief="solid",
                                     padx=5)
            reply_time = tk.Label(container,
                                  text=msg.get("reply_time", ""),
                                  anchor=tk.W,
                                  bg="#e0ffe0",
                                  bd=1,
                                  relief="solid",
                                  padx=5)

            reply_nickname.grid(row=reply_row, column=0, sticky="nsew")
            reply_content.grid(row=reply_row, column=1, sticky="nsew")
            reply_time.grid(row=reply_row, column=2, sticky="nsew")

        # 配置列权重
        container.grid_columnconfigure(0, weight=0, minsize=100)
        container.grid_columnconfigure(1, weight=0, minsize=200)
        container.grid_columnconfigure(2, weight=0, minsize=150)

        container.update_idletasks()
        canvas.config(scrollregion=canvas.bbox("all"))

        # 绑定鼠标滚轮事件
        def _on_mousewheel(event):
            canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

        canvas.bind_all("<MouseWheel>", _on_mousewheel)
    def show_prompt_edit(self):
        for widget in self.display_frame.winfo_children():
            widget.destroy()

        prompt_content = self.bot.ai.prompt_content

        text_frame = tk.Frame(self.display_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)

        self.prompt_text = tk.Text(text_frame)
        self.prompt_text.insert(tk.END, prompt_content)
        self.prompt_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = Scrollbar(text_frame, command=self.prompt_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.prompt_text.configure(yscrollcommand=scrollbar.set)

        save_button = tk.Button(self.display_frame, text="保存提示词", command=self.save_prompt)
        save_button.pack(pady=10)


    def save_prompt(self):
        new_prompt = self.prompt_text.get("1.0", tk.END).strip()
        try:
            with open(PROMPT_FILE, 'w', encoding='utf-8') as f:
                f.write(new_prompt)
            self.bot.ai.prompt_content = new_prompt
            messagebox.showinfo("提示", "提示词保存成功")
        except Exception as e:
            messagebox.showerror("错误", f"保存提示词时出错: {str(e)}")

    def show_config_edit(self):
        # 清空显示框架中的所有部件
        for widget in self.display_frame.winfo_children():
            widget.destroy()

        # 新增：处理文件不存在的情况
        if not os.path.exists(self.config_path):
            self._create_default_config()

        try:
            with open(self.config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
        except FileNotFoundError:
            messagebox.showerror("错误", f"配置文件不存在：{self.config_path}")
            return
        except json.JSONDecodeError as e:
            messagebox.showerror("错误", f"配置文件格式错误：\n{str(e)}")
            return
        except Exception as e:
            messagebox.showerror("错误", f"读取配置失败：\n{str(e)}")
            return

        # 创建文本框显示配置信息
        text_frame = tk.Frame(self.display_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)

        self.config_text = tk.Text(text_frame)
        self.config_text.insert(tk.END, json.dumps(config, indent=4, ensure_ascii=False))
        self.config_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = Scrollbar(text_frame, command=self.config_text.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.config_text.configure(yscrollcommand=scrollbar.set)

        # 创建保存按钮
        save_button = tk.Button(self.display_frame, text="保存配置", command=self.save_config)
        save_button.pack(pady=10)

    def save_config(self):
        # 获取文本框中的内容
        new_config_text = self.config_text.get("1.0", tk.END).strip()

        try:
            # 解析新的配置信息
            new_config = json.loads(new_config_text)

            # 保存到配置文件
            with open('config.json', 'w', encoding='utf-8') as f:
                json.dump(new_config, f, indent=4, ensure_ascii=False)

            messagebox.showinfo("提示", "配置保存成功")
        except json.JSONDecodeError:
            messagebox.showerror("错误", "配置信息格式错误，请检查")
